package controller

import (
	"github.com/fatih/color"
	"github.com/gin-gonic/gin"
	"github.com/ifnk/micro-blog/internal/blog/global"
	"github.com/ifnk/micro-blog/internal/blog/middleware"
	"github.com/ifnk/micro-blog/internal/pkg/base"
	response "github.com/ifnk/micro-blog/internal/pkg/http"
	"github.com/ifnk/micro-blog/internal/pkg/jwt"
	"github.com/ifnk/micro-blog/protobuf/post_pb"
	"github.com/infobloxopen/atlas-app-toolkit/query"
	"strconv"
	"strings"
)

func InitPostController(r *gin.RouterGroup) {
	api := r.Group("/post")
	api.GET("", getPosts)
	api.GET("/:id", getPost)
	// 这个 要 使用 jwt 和 casbin 中间件
	api.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()) // 在这行之前的api 裸奔,之后的受保护
	api.POST("", createPost)
	api.PUT("/:id", updatePost)
	api.DELETE("/:id", deletePost)
}

func createPost(c *gin.Context) {
	var input post_pb.Post
	_ = c.ShouldBindJSON(&input)
	// 从header 头里面 获取 用户 信息
	token := c.Request.Header.Get("x-token")
	j := jwt.NewJwt(global.Logger, global.Conf)
	claims, err := j.ParseToken(token)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	input.UserId = uint64(claims.ID)

	res, err := global.PostClient.Create(c, &post_pb.CreatePostRequest{Payload: &input})
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	orm, err := res.GetResult().ToORM(c)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(orm, c)
}

func getPost(c *gin.Context) {
	idStr := c.Param("id")
	id, _ := strconv.Atoi(strings.TrimSpace(idStr))
	res, err := global.PostClient.Read(c, &post_pb.ReadPostRequest{Id: uint64(id)})
	orm, err := res.GetResult().ToORM(c)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(orm, c)
}
func deletePost(c *gin.Context) {
	idStr := c.Param("id")
	id, _ := strconv.Atoi(strings.TrimSpace(idStr))
	res, err := global.PostClient.Delete(c, &post_pb.DeletePostRequest{Id: uint64(id)})
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(res, c)
}
func updatePost(c *gin.Context) {
	var input post_pb.PostORM
	idStr := c.Param("id")
	id, _ := strconv.Atoi(strings.TrimSpace(idStr))
	_ = c.ShouldBindJSON(&input)
	pb, _ := input.ToPB(c)
	pb.Id = uint64(id)
	res, err := global.PostClient.Update(c, &post_pb.UpdatePostRequest{Payload: &pb})
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	orm, _ := res.GetResult().ToORM(c)
	response.OkWithData(orm, c)
}
func getPosts(c *gin.Context) {
	var params base.PageEntity
	_ = c.ShouldBindQuery(&params)
	offset := int32(params.PageIndex-1) * int32(params.PageSize)
	limit := int32(params.PageSize)
	client := global.PostClient
	color.Blue("client -> %+v", client)
	menuRes, err := global.PostClient.List(c, &post_pb.ListPostRequest{Paging: &query.Pagination{Offset: offset, Limit: limit}})
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	global.Logger.Infof("menuRes -> %+v", menuRes)

	var pbResponse []post_pb.PostORM
	for _, item := range menuRes.GetResults() {
		orm, err := item.ToORM(c)
		if err != nil {
			response.FailWithMessage(err.Error(), c)
			return
		}
		pbResponse = append(pbResponse, orm)
	}
	var total int32
	if menuRes.PageInfo == nil {
		total = 0
	} else {
		total = menuRes.PageInfo.Size
	}

	response.OkWithData(PostPageRes{
		Total: total,
		Items: pbResponse,
	}, c)
}

type PostPageRes struct {
	Total int32
	Items []post_pb.PostORM
}
